<template>
    <el-container class="palyer-main">
        <el-header height="35px">
            <span style="float: left">直播设置</span>
            <span>xxx直播间(已播 ：03:35:12)</span>
            <span style="float: right">聊天室</span>
        </el-header>

        <el-container>
            <el-aside width="250px" class="palyer-main-left">
                <div class="live-item">
                    <el-select v-model="videoSourceVal" placeholder="摄像头选择" style="width: 130px">
                        <el-option v-for="(item, index) in videoSourceOption" :key="index" :label="item.label"
                            :value="item.value" />
                    </el-select>
                    <el-switch v-model="videoActive" active-text="开" inactive-text="关" @change="videoActiveChange" />
                </div>
                <div class="live-item">
                    <el-select v-model="audioInputVal" placeholder="麦克风选择" style="width: 130px">
                        <el-option v-for="(item, index) in audioInputOption" :key="index" :label="item.label"
                            :value="item.value" />
                    </el-select>
                    <el-switch v-model="audioInputActive" active-text="开" inactive-text="关"
                        @change="audioInputActiveChange" />
                </div>
                <div class="live-item">
                    <i class="el-icon-video-camera" />
                    <span>屏幕录制</span>
                    <el-switch v-model="screenRecoderActive" class="live-item-switch" active-text="开" inactive-text="关"
                        @change="screenRecoderChange" />
                </div>
                <el-button v-if="liveBtn" type="success" size="medium" icon="el-icon-mic" class="live-btn"
                    @click="startRecord">开始直播</el-button>
                <el-button v-else type="success" size="medium" icon="el-icon-mic" class="live-btn"
                    @click="stopRecord">结束直播</el-button>
            </el-aside>

            <el-main class="palyer-main-video">
                <el-main :style="{ height: tableHeight + 'px' }">
                    <video ref="canvsVideo" autoplay controls width="557px" height="412px" />
                </el-main>
                <el-footer height="120px" />
            </el-main>

            <el-aside width="290px" class="palyer-main-right">
                <div style="padding: 15px 25px;height: 82px;">
                    <el-avatar size="large" :src="circleUrl" class="chat-room-user" />
                    <div class="chat-room-info">
                        <div>陈晓二</div>
                        <div>
                            <i class="el-icon-view" title="当前在线人数" />&nbsp;<span>19</span>
                        </div>
                    </div>
                </div>
                
                <el-tabs v-model="activeName" stretch @tab-click="handleClick">
                    <el-tab-pane label="聊天" name="first">
                        <chatroom />
                    </el-tab-pane>
                    <el-tab-pane label="在线(26)" name="second">
                        <userlist />
                    </el-tab-pane>
                    <el-tab-pane label="问答" name="third">
                        <answers />
                    </el-tab-pane>
                </el-tabs>
            </el-aside>
        </el-container>

        <video ref="localVideo" autoplay style="display: none" />
        <video ref="screenVideo" autoplay style="display: none" />
        <canvas ref="canvs" style="display: none" />
    </el-container>
</template>
<script>
import { mapGetters } from 'vuex'
import chatroom from '../module/chatroom'
import answers from '../module/answers'
import userlist from '../module/userlist'

export default {
    name: 'LivePalyer',
    components: {
        chatroom, answers, userlist
    },
    data() {
        return {
            SCREEN_WIDTH: 1024,
            SCREEN_HEIGHT: 640,
            CAMERA_VIDEO_WIDTH: 200,
            CAMERA_VIDEO_HEIGHT: 150,

            screenHeight: 0,

            videoActive: false,
            videoSourceVal: '',
            videoSourceOption: [],
            audioInputActive: false,
            audioInputVal: '',
            audioInputOption: [],
            audioOutActive: false,
            audioOutputVal: '',
            audioOutputOption: [],
            screenRecoderActive: false,

            circleUrl: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png',

            activeName: 'first',

            liveBtn: true,
            roomid: '1111',
            fileHeader: []
        }
    },
    computed: {
        ...mapGetters([
            'sysHospital',
            'userId',
            'username'
        ]),
        tableHeight: function () {
            return window.screen.height - 352
        }
    },
    created() {
        if (this.$socket.disconnected) {
            this.$socket.connect()
        }
        this.getDevices()
        this.getUserMedia()
    },

    mounted() {
        this.canvs = this.$refs.canvs
        this.canvs.width = this.SCREEN_WIDTH
        this.canvs.height = this.SCREEN_HEIGHT
        this.canvsVideo = this.$refs.canvsVideo
        this.localVideo = this.$refs.localVideo
        this.screenVideo = this.$refs.screenVideo

        this._context2d = this.canvs.getContext('2d')
        setTimeout(this._animationFrameHandler.bind(this), 30)
    },

    methods: {
        RecordLoop() {
            if (this.mediaRecorder.state !== 'inactive') {
                this.mediaRecorder.stop()
            }
            if (this.mediaRecorder.state !== 'recording') {
                this.mediaRecorder.start()
            }
            setTimeout(this.RecordLoop, 2500)
        },

        // 拿到媒体流
        startRecord() {
            this.liveBtn = false
            console.log(`start Record`)
            const _this = this
            // 1. Create a `MediaSource`
            this.mediaSource = new MediaSource()
            // 2. Create an object URL from the `MediaSource`
            var url = URL.createObjectURL(this.mediaSource)
            // 3. Set the video's `src` to the object URL
            this.canvsVideo.src = url
            this.sourceBuffer = null
            this.mediaSource.addEventListener('sourceopen', async function () {
                URL.revokeObjectURL(_this.localVideo.src)
                _this.sourceBuffer = _this.mediaSource.addSourceBuffer('video/webm; codecs=opus,vp9')
                _this.sourceBuffer.mode = 'sequence'// 不然需要添加时间戳
                _this.sourceBuffer.addEventListener('updateend', function () {
                })
            })
            this.RecordLoop()
        },
        stopRecord() {
            this.liveBtn = true
            this.canvsVideo.srcObject = null
            this.mediaRecorder.stop()
            URL.revokeObjectURL(this.canvsVideo.src)
        },

        async getUserMedia() {
            const _this = this
            this._stream = new MediaStream()
            if (this.videoActive) {
                // 视频
                if (navigator.mediaDevices.getUserMedia) {
                    // 最新标准API
                    this.cameraStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: false })
                } else if (navigator.webkitGetUserMedia) {
                    // webkit内核浏览器
                    this.cameraStream = await navigator.webkitGetUserMedia({ video: true, audio: false })
                } else if (navigator.mozGetUserMedia) {
                    // Firefox浏览器
                    this.cameraStream = await navigator.mozGetUserMedia({ video: true, audio: false })
                } else if (navigator.getUserMedia) {
                    // 旧版API
                    this.cameraStream = await navigator.getUserMedia({ video: true, audio: false })
                }
                this.localVideo.srcObject = this.cameraStream
            }
            if (this.screenRecoderActive) {
                this.captureStream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: false })
                this.screenVideo.srcObject = this.captureStream
            }
            this._audioStream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true })
            if (this.audioInputActive) {
                this._audioStream.getAudioTracks().forEach(value => this._stream.addTrack(value))
            }
            this._audioStream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true })
            this._audioStream.getAudioTracks().forEach(value => this._stream.addTrack(value))

            const playerCanvasStream = this.canvs.captureStream()
            playerCanvasStream.getTracks().forEach(t => this._stream.addTrack(t))

            const options = {
                mimeType: 'video/webm; codecs=opus,vp9'
            }
            if (!MediaRecorder.isTypeSupported(options.mimeType)) {
                this.$message.error(`${options.mimeType} is not supported!`)
                return
            }
            this.mediaRecorder = new MediaRecorder(this._stream, options)
            // 当录制的数据可用时
            this.mediaRecorder.ondataavailable = async function (e) {
                if (e.data.size > 0) {
                    var reader = new FileReader()
                    reader.readAsArrayBuffer(e.data)
                    reader.onloadend = function (e) {
                        _this.sourceBuffer.appendBuffer(reader.result)
                        // if (_this.joinRoomState === 'joinedRoom') {
                        _this.$socket.emit('sendLiveMessage', _this.roomid, reader.result)
                        // }
                    }
                }
            }
        },

        getDevices() {
            if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
                this.$message.error('不支持获取设备信息！')
            } else {
                navigator.mediaDevices.enumerateDevices()
                    .then(this.showDevice)
                    .catch((err) => {
                        console.log(err.name + ':' + err.message)
                    })
            }
        },
        showDevice(deviceInfos) {
            const _this = this
            deviceInfos.forEach(function (deviceinfo) {
                const option = {
                    label: deviceinfo.label,
                    value: deviceinfo.deviceId
                }
                if (deviceinfo.kind === 'audioinput') {
                    _this.audioInputOption.push(option)
                } else if (deviceinfo.kind === 'audiooutput') {
                    _this.audioOutputOption.push(option)
                } else if (deviceinfo.kind === 'videoinput') {
                    _this.videoSourceOption.push(option)
                }
            })
        },
        
        async recordScreenStream() {
            if (!this.screenRecoderActive) {
                return
            }
            this.captureStream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: false })
            this.screenVideo.srcObject = this.captureStream
        },
        async recordCameraStream() {
            if (this.videoActive) {
                // 视频
                if (navigator.mediaDevices.getUserMedia) {
                    // 最新标准API
                    this.cameraStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: false })
                } else if (navigator.webkitGetUserMedia) {
                    // webkit内核浏览器
                    this.cameraStream = await navigator.webkitGetUserMedia({ video: true, audio: false })
                } else if (navigator.mozGetUserMedia) {
                    // Firefox浏览器
                    this.cameraStream = await navigator.mozGetUserMedia({ video: true, audio: false })
                } else if (navigator.getUserMedia) {
                    // 旧版API
                    this.cameraStream = await navigator.getUserMedia({ video: true, audio: false })
                }
                this.localVideo.srcObject = this.cameraStream
            }
        },
        async recordAudioStream() {
            if (this.audioInputActive) {
                this._audioStream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true })
                this._audioStream.getAudioTracks().forEach(value => this._stream.addTrack(value))
            }
        },
        handleClick(tab, event) {
            console.log(tab, event)
        },
        _animationFrameHandler() {
            if (this.screenVideo && this.screenRecoderActive) {
                this._context2d.drawImage(this.screenVideo, 0, 0, this.SCREEN_WIDTH, this.SCREEN_HEIGHT)
            }
            if (this.localVideo && this.videoActive) {
                if (this.screenRecoderActive) {
                    this._context2d.drawImage(
                        this.localVideo,
                        this.SCREEN_WIDTH - this.CAMERA_VIDEO_WIDTH,
                        this.SCREEN_HEIGHT - this.CAMERA_VIDEO_HEIGHT,
                        this.CAMERA_VIDEO_WIDTH,
                        this.CAMERA_VIDEO_HEIGHT
                    )
                } else {
                    this._context2d.drawImage(
                        this.localVideo, 0, 0, this.SCREEN_WIDTH, this.SCREEN_HEIGHT
                    )
                }
            }
            setTimeout(this._animationFrameHandler.bind(this), 30)
        },
        screenRecoderChange(callback) {
            this.screenRecoderActive = callback
            if (this.screenRecoderActive) {
                this.recordScreenStream()
            }
        },
        videoActiveChange(callback) {
            this.videoActive = callback
            if (this.videoActive) {
                this.recordCameraStream()
            }
        },
        audioInputActiveChange(callback) {
            this.audioInputActive = callback
            if (this.audioInputActive) {
                this.recordAudioStream()
            }
        }
        // audioOutActiveChange() {
        //   this.audioOutActive = !this.audioInputActive
        // }
    },
    sockets: {
        /**
         * socket自带3个事件connect，disconnect，reconnect
         * **/
        connect: function () {
            // 与socket.io连接后回调
            console.log('socket connected')
            this.$socket.emit('joinRoom', this.roomid)
        },
        disconnect: function () {
            console.log('socket disconnect')
        },
        reconnect: function () {
            console.log('socket reconnect')
        },
        joinedRoom: function (data) {
            // 加入成功后不能再次连接,可以离开
            this.connectFlag = true
            this.leaveFlag = false
            // 改变状态
            this.joinRoomState = 'joinedRoom'
            console.log('joinedRoom')
        },
        otherJoin: function (data) {
            console.log('otherJoin' + data.room)
            if (this.joinRoomState === 'joinedRoom') {
                const msg = `${data.username}加入会议室（${data.room}），当前有${data.numUsers}人`
                this.$message.success(msg)
            }
        },
        roomFull: function (data) {
            this.joinRoomState = 'leavedRoom'
            // 可以再次连接
            this.connectFlag = false
            this.leaveFlag = true
            this.$message.error('房间人数已满，请稍后重试！')
            this.$socket.disconnect()
            console.log('leavedRoom')
        },
        leaveRoomed: function (data) {
            this.connectFlag = false
            this.leaveFlag = true
            this.joinRoomState = 'leavedRoom'
            this.$socket.disconnect()
            console.log('leavedRoom')
        },
        sayBye: function (data) {
            this.connectFlag = false
            this.leaveFlag = true
            this.joinRoomState = 'leavedRoom'
            this.$socket.disconnect()
            console.log('leavedRoom')
        },
        receivedMessage: function (msg) {
        }
    }
}
</script>
<style scoped>
.palyer-main {
    padding: 10px 10px;
}

.palyer-main-left {
    border: 1px solid #e5e4e4;
    margin-right: 10px;
    border-radius: 10px;
}

.palyer-main-right {
    border: 1px solid #e5e4e4;
    margin-left: 10px;
    border-radius: 10px;
}

.palyer-main-video {
    padding: 10px;
    border: 1px solid #e5e4e4;
}

.el-header {
    padding: 0 126px 0 95px;
    color: #333;
    text-align: center;
    line-height: 35px;
}

.el-footer {
    color: #333;
    text-align: center;
}

.el-aside {
    background: #fff;
    color: #333;
    text-align: center;
    margin-bottom: 0;
    padding: 8px 5px;
}

.live-item {
    padding-top: 10px;
    padding-bottom: 10px;
    border-bottom: 1px solid #eee
}

.live-item-switch {
    float: right;
    padding-top: 10px;
    padding-right: 8px;
}

.live-btn {
    position: absolute;
    left: 0;
    bottom: 0;
    margin-left: 15px;
    padding: 10px 80px;
}

.chat-room-info {
    float: left;
    padding-left: 10px;
    color: #aea9a9;
}

.chat-room-user {
    position: relative;
    float: left;
}

.el-avatar--large {
    width: 60px;
    height: 60px;
}

.el-main {
    padding: 0;
    color: #333;
    text-align: center;
}

body>.el-container {
    margin-bottom: 40px;
}

.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {}

.el-container:nth-child(7) .el-aside {}
</style>
  
  